/*
*Copyright 2021-2023 NERCIS
*
*Licensed under the Apache License, Version 2.0 (the "License");
*you may not use this file except in compliance with the License.
*You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*Unless required by applicable law or agreed to in writing, software
*distributed under the License is distributed on an "AS IS" BASIS,
*WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*See the License for the specific language governing permissions and
*limitations under the License.
*/

package cn.ac.nercis.pes.community.controller.project;

import cn.ac.nercis.pes.community.component.controls.PesComboBox;
import cn.ac.nercis.pes.community.component.controls.PesTextField;
import cn.ac.nercis.pes.community.component.dialog.MessageDialog;
import cn.ac.nercis.pes.community.component.dialog.MessageType;
import cn.ac.nercis.pes.community.controller.base.GlobalEventHandle;
import cn.ac.nercis.pes.community.mapper.manage.TestedUnitViewMapper;
import cn.ac.nercis.pes.community.mapper.project.ProjectViewMapper;
import cn.ac.nercis.pes.community.model.vo.manage.TestedUnitVO;
import cn.ac.nercis.pes.community.model.vo.project.ProjectVO;
import cn.ac.nercis.pes.community.support.FXMLController;
import cn.ac.nercis.pes.community.utils.GuiStore;
import cn.ac.nercis.pes.community.utils.IconUtils;
import cn.ac.nercis.pes.community.utils.SpringUtils;
import cn.ac.nercis.pes.community.views.project.AddSystemView;
import cn.ac.nercis.pes.community.views.project.TaskManageView;
import cn.ac.nercis.pes.model.dto.common.Result;
import cn.ac.nercis.pes.model.dto.manage.TestedUnitDTO;
import cn.ac.nercis.pes.model.dto.project.ProjectDTO;
import cn.ac.nercis.pes.model.dto.project.ProjectDetailDTO;
import cn.ac.nercis.pes.service.manage.TestedUnitService;
import cn.ac.nercis.pes.service.project.ProjectService;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * 添加项目管理控制器
 * @author zpy
 * @version 1.0.0
 */
@FXMLController
public class AddProjectController implements Initializable, GlobalEventHandle {

    @FXML
    private StackPane page;
    @FXML
    private Label titleLabel;
    @FXML
    private Button saveButton;
    @FXML
    private Button saveAndButton;
    @FXML
    private Button backButton;
    @FXML
    private PesTextField numberTF;
    @FXML
    private PesTextField nameTF;
    @FXML
    private PesTextField requesterUnitTF;
    @FXML
    private PesComboBox testedUnitCbx;

    @FXML
    private PesTextField testUnitNameTF;
    @FXML
    private PesTextField testUnitAddressTF;
    @FXML
    private PesTextField testUnitPostalCodeTF;
    @FXML
    private PesTextField testUnitManageTF;
    @FXML
    private PesTextField contactPersonTF;
    @FXML
    private PesTextField contactPositionTF;
    @FXML
    private PesTextField contactDepartmentTF;
    @FXML
    private PesTextField contactTelTF;
    @FXML
    private PesTextField contactPhoneTF;
    @FXML
    private PesTextField contactEmailTF;

    private final TestedUnitService testedUnitService;
    private final ProjectService projectService;
    private final ProjectVO projectData = new ProjectVO();
    private final TestedUnitVO testedUnitData = new TestedUnitVO();
    private final List<TestedUnitDTO> testedUnits = new ArrayList<>();
    private final BooleanProperty notEditModel = new SimpleBooleanProperty(false);

    @Autowired
    public AddProjectController(TestedUnitService testedUnitService,
                                ProjectService projectService) {
        this.testedUnitService = testedUnitService;
        this.projectService = projectService;
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        titleLabel.setGraphic(IconUtils.getGlyph("project-icon","title-icon"));
        saveButton.setGraphic(IconUtils.getGlyph("save-button-icon","btn-icon"));
        saveAndButton.setGraphic(IconUtils.getGlyph("save-two-button-icon","btn-icon"));
        backButton.setGraphic(IconUtils.getGlyph("back-button-icon","btn-icon"));
        //新增、编辑控件初始化
        initProjectControl();
        GuiStore.applyQuickSave(this.page,this::onGlobalSave);
    }

    /**
     * 初始化数据(新增)
     */
    public void initializeData() {
        //新增模式
        notEditModel.set(true);
        //初始化验证信息
        resetValidation();
        //初始化数据
        initAddProjectData();
    }

    /**
     * 初始化数据(编辑)
     */
    public void initializeData(ProjectDTO projectDTO){
        //编辑模式
        notEditModel.set(false);
        //初始化验证信息
        resetValidation();
        //初始化数据
        initModifyProjectData(projectDTO);
    }

    @FXML
    private void onBack(){
        //返回到项目任务页面
        var taskManageView = SpringUtils.getBean(TaskManageView.class).getView();
        GuiStore.setMainBodyContent(taskManageView);
    }

    @FXML
    public void onSave(){
        saveProject(false);
    }

    @FXML
    public void onSaveAnd(){
        saveProject(true);
    }

    @Override
    public void onGlobalSave() {
        saveProject(false);
    }

    public BooleanProperty notEditModelProperty(){
        return this.notEditModel;
    }

    public boolean isNotEditModel(){
        return this.notEditModel.get();
    }

    private void saveProject(boolean isContinue){
        this.projectData.setNumber(StringUtils.trim(this.projectData.getNumber()));
        this.projectData.setName(StringUtils.trim(this.projectData.getName()));
        if (!validate()) {
            return;
        }
        TestedUnitDTO testedUnitDTO = TestedUnitViewMapper.INSTANCE.toDTO(this.testedUnitData);
        ProjectDetailDTO projectDetailDTO = ProjectViewMapper.INSTANCE.toDTO(this.projectData);
        CompletableFuture.supplyAsync(() -> testedUnitService.save(testedUnitDTO))
                .thenApply(res -> {
                    if (res.isSuccess()) {
                        projectDetailDTO.setTestedUnitId(res.getData().getId());
                        return projectService.save(projectDetailDTO);
                    } else {
                        return Result.failed(res.getMsg());
                    }
                })
                .thenAccept(res -> Platform.runLater(() -> {
                    if (res.isSuccess()) {
                        SpringUtils.getBean(TaskManageController.class).initializeData();
                        if (isContinue) {
                            //跳转到新增系统页面
                            var addSystemView = SpringUtils.getBean(AddSystemView.class).getView();
                            //保存项目信息并跳转到添加系统信息页面
                            GuiStore.setMainBodyContent(addSystemView);
                            SpringUtils.getBean(AddSystemController.class).initializeData(((ProjectDTO) res.getData()).getId());
                        } else {
                            MessageDialog.builder()
                                    .withType(MessageType.SUCCESS).withMessage("保存成功")
                                    .withContainer(this.page)
                                    .build()
                                    .show();
                            //返回到项目管理页面
                            onBack();
                        }
                    } else {
                        MessageDialog.builder()
                                .withType(MessageType.FAIL).withMessage(res.getMsg())
                                .withContainer(this.page)
                                .build()
                                .show();
                    }
                }));
    }

    private boolean validate(){
        this.numberTF.validate();
        this.nameTF.validate();
        this.testUnitNameTF.validate();
        return this.nameTF.validate() && this.numberTF.validate()
                && (StringUtils.isBlank(this.projectData.getTestedUnitId()) || this.testUnitNameTF.validate());
    }

    private void initProjectControl(){
        //控件绑定到数据模型
        this.numberTF.textProperty().bindBidirectional(projectData.numberProperty());
        this.nameTF.textProperty().bindBidirectional(projectData.nameProperty());
        this.requesterUnitTF.textProperty().bindBidirectional(projectData.requesterUnitProperty());
        this.testedUnitCbx.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            var selectUnit = this.testedUnits.stream()
                    .filter(tu->StringUtils.equals(tu.getName(),newValue))
                    .findFirst()
                    .orElse(TestedUnitDTO.builder().build());
            initTestedUnitData(selectUnit);
            this.projectData.setTestedUnitId(testedUnitData.getId());
        });
        //绑定被测单位到数据模型
        this.testUnitNameTF.textProperty().bindBidirectional(testedUnitData.nameProperty());
        this.testUnitAddressTF.textProperty().bindBidirectional(testedUnitData.addressProperty());
        this.testUnitPostalCodeTF.textProperty().bindBidirectional(testedUnitData.postalCodeProperty());
        this.testUnitManageTF.textProperty().bindBidirectional(testedUnitData.manageProperty());
        this.contactPersonTF.textProperty().bindBidirectional(testedUnitData.contactPersonProperty());
        this.contactPositionTF.textProperty().bindBidirectional(testedUnitData.contactPositionProperty());
        this.contactDepartmentTF.textProperty().bindBidirectional(testedUnitData.contactDepartmentProperty());
        this.contactTelTF.textProperty().bindBidirectional(testedUnitData.contactTelProperty());
        this.contactPhoneTF.textProperty().bindBidirectional(testedUnitData.contactPhoneProperty());
        this.contactEmailTF.textProperty().bindBidirectional(testedUnitData.contactEmailProperty());
    }

    private void resetValidation(){
        this.numberTF.resetValidation();
        this.nameTF.resetValidation();
        this.testUnitNameTF.resetValidation();
    }
    private void initAddProjectData(){
        projectData.setId("");
        projectData.setName("");
        projectData.setNumber("");
        projectData.setTestedUnitId("");
        projectData.setRequesterUnit("");
        CompletableFuture.supplyAsync(this.testedUnitService::findAll)
                .thenAccept(res-> Platform.runLater(()->{
                    //加载被测单位列表
                    testedUnitCbx.setItems(testedUnitItems(res));
                    this.testedUnits.stream()
                            .findFirst()
                            .ifPresent(r->{
                                projectData.setTestedUnitId(r.getId());
                                testedUnitCbx.getSelectionModel().select(r.getName());
                            });
                }));
    }

    private void initModifyProjectData(ProjectDTO projectDTO){
        projectData.setId(projectDTO.getId());
        projectData.setName(projectDTO.getName());
        projectData.setNumber(projectDTO.getNumber());
        projectData.setTestedUnitId(projectDTO.getTestedUnitId());
        projectData.setRequesterUnit(projectDTO.getRequesterUnit());
        CompletableFuture.supplyAsync(this.testedUnitService::findAll)
                .thenAccept(res-> Platform.runLater(()->{
                    //加载被测单位列表
                    testedUnitCbx.setItems(testedUnitItems(res));
                    var defaultItem = this.testedUnits.stream()
                            .filter(tu->StringUtils.equals(tu.getId(),projectDTO.getTestedUnitId()))
                            .map(TestedUnitDTO::getName)
                            .findFirst()
                            .orElse("手动创建");
                    testedUnitCbx.getSelectionModel().select(defaultItem);
                }));
    }

    private void initTestedUnitData(TestedUnitDTO unitDTO){
        testedUnitData.setId(unitDTO.getId());
        testedUnitData.setName(unitDTO.getName());
        testedUnitData.setAddress(unitDTO.getAddress());
        testedUnitData.setPostalCode(unitDTO.getPostalCode());
        testedUnitData.setManage(unitDTO.getManage());
        testedUnitData.setContactPerson(unitDTO.getContactPerson());
        testedUnitData.setContactPosition(unitDTO.getContactPosition());
        testedUnitData.setContactDepartment(unitDTO.getContactDepartment());
        testedUnitData.setContactTel(unitDTO.getContactTel());
        testedUnitData.setContactPhone(unitDTO.getContactPhone());
        testedUnitData.setContactEmail(unitDTO.getContactEmail());
    }

    private ObservableList<String> testedUnitItems(List<TestedUnitDTO> res){
        this.testedUnits.clear();
        this.testedUnits.addAll(res);
        ObservableList<String> items = FXCollections.observableList(res.stream()
                .map(TestedUnitDTO::getName)
                .collect(Collectors.toList()));
        items.add("手动创建");
        return items;
    }

}